﻿using DotNetCommon.Extensions;
using furion.blog.Application.Contracts;
using furion.blog.Application.CustomMapper;
using furion.blog.Domain.IRepositories;
using furion.blog.Domain.MySQL;
using furion.blog.Domain.Query.Dept;
using furion.blog.Domain.Shared.Dto.Dept;
using furion.blog.Domain.Shared.Enum;
using furion.blog.Domain.Shared.Vo.Dept;
using furion.blog.Utils;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace furion.blog.Application
{
    public class DeptService : IDeptService, ISingleton
    {
        private readonly IDeptRepository _deptRepository;
        private readonly DeptMapper _deptMapper;
        private readonly IUserService _userService;
        public DeptService(IDeptRepository deptRepository,DeptMapper deptMapper)
        {
            this._deptRepository = deptRepository;
            this._deptMapper = deptMapper;
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DeptDetailVO> Detail(long id)
        {
            Dept dept = await this._deptRepository.FindById(id);
            if (dept == null)
            {
                return null;
            }
            return dept.Adapt<DeptDetailVO>();
        }

        /// <summary>
        /// 部门树
        /// </summary>
        /// <param name="parentId">父级ID</param>
        /// <returns></returns>
        public async Task<object> Tree(long? parentId)
        {
            List<Dept> list = await this._deptRepository.All(new Domain.Query.Dept.DeptDetailQuery { FuzzyQuery = false, IsDelete = YesOrNoEnum.No.ToString() });
            List<DeptDetailVO> data = new List<DeptDetailVO>();
            list.ForEach(t =>
            {
                data.Add(new DeptDetailVO
                {
                    Id = t.DeptId,
                    DeptId = t.DeptId,
                    DeptName = t.DeptName,
                    Name = t.DeptName,
                    ParentId = t.ParentId,
                    Ancestors = t.Ancestors,
                    DeptEn = t.DeptEn,
                    CreatedTime = t.CreatedTime,
                    Children = null,
                });
            });
            return data.FetchToTree(i => i.DeptId, i => i.ParentId, i => i.Children, i => i.ParentId == parentId);
        }

        /// <summary>
        /// 新增部门
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task Add(DeptCreateDto dto) {
            Dept dept = await this._deptRepository.First(new DeptDetailQuery { ParentId = dto.ParentId,DeptName = dto.DeptName,IsDelete = YesOrNoEnum.No.ToString() }.Exp());
            if (dept != null) {
                throw Oops.Oh("部门名称已存在");
            }
            dept = await this._deptRepository.First(new DeptDetailQuery { ParentId = dto.ParentId, DeptEn = dto.DeptEn, IsDelete = YesOrNoEnum.No.ToString() }.Exp());
            if (dept != null)
            {
                throw Oops.Oh("部门简称已存在");
            }
            string ancestors = await getAncestors(dto.ParentId);
            if (ancestors == null || ancestors != dto.Ancestors) {
                throw Oops.Oh("提交数据有误");
            }
            dept = dto.Adapt<Dept>();
            dept.DeptId = IdUtil.Id();
            await this._deptRepository.Save(dept);
        }

        /// <summary>
        /// 更新部门信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task Update(DeptUpdateDto dto) {
            Dept dept = null;
            dept = await this._deptRepository.First(new DeptDetailQuery { DeptIdNE = dto.DeptId,DeptName = dto.DeptName , ParentId = dto.ParentId , IsDelete = YesOrNoEnum.No.ToString() }.Exp());
            if (dept != null) {
                throw Oops.Oh("部门名称已存在");
            }
            dept = await this._deptRepository.First(new DeptDetailQuery { DeptIdNE = dto.DeptId, DeptEn = dto.DeptEn, ParentId = dto.ParentId, IsDelete = YesOrNoEnum.No.ToString() }.Exp());
            if (dept != null)
            {
                throw Oops.Oh("部门简称已存在");
            }
            string ancestors = await getAncestors(dto.ParentId);
            if (ancestors == null || ancestors != dto.Ancestors)
            {
                throw Oops.Oh("提交数据有误");
            }
            dept = await this._deptRepository.FindById((long)dto.DeptId);
            if (dept == null)
            {
                throw Oops.Oh("信息不存在");
            }
            dept = this._deptMapper.Map(dto,dept);
            await this._deptRepository.Update(dept);
        }

        /// <summary>
        /// 通过上级ID获取当前部门的ancestors
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private async Task<string> getAncestors(long? parentId) {
            if (parentId != null && parentId != 0L) {
                Dept dept = await this._deptRepository.FindById((long)parentId);
                if (dept == null)
                {
                    return null;
                }
                else {
                    return dept.Ancestors + "," + dept.DeptId;
                }
            }
            else
            {
                return "0";
            }
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task Delete(long id, long userId) {
            Dept dept = await this._deptRepository.FindById(id);
            if (dept != null) {
                throw Oops.Oh("部门信息不存在");
            }
            long count = await this._deptRepository.Count(new DeptDetailQuery { ParentId = id,IsDelete = YesOrNoEnum.No.ToString() }.Exp());
            if (count > 0) {
                throw Oops.Oh("存在下级部门，无法删除");
            }
            count = await this._userService.Count(new Domain.Query.User.UserDetailQuery { DeptId = id,IsDelete = YesOrNoEnum.No.ToString() });
            if (count > 0) {
                throw Oops.Oh("部门存在账号，无法删除");
            }
            dept.IsDelete = YesOrNoEnum.Yes.ToString();
            dept.UpdatedBy = userId;
            dept.UpdatedTime = DateTime.Now;
            await this._deptRepository.Update(dept);
        }

    }
}
